package com.petecapra.cashflow.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.Digits;
import javax.validation.constraints.NotNull;

import org.hibernate.annotations.Cascade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;

import com.petecapra.cashflow.model.dao.AccountManager;
import com.petecapra.cashflow.model.dao.AccountTransactionManager;
import com.petecapra.cashflow.model.dao.ScheduleManager;

@Entity
@Table(name="tblAccounts")
@Configurable
public class Account extends BaseDomainObject<AccountManager> implements Serializable {

	private static final long serialVersionUID = 1L;
	
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private long id;

	@NotNull	
    private String name;

	@NotNull
    @Digits(integer = 7, fraction = 2)
    private Double balance;
	
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "account")
    @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    private List<Schedule> schedules = new ArrayList<Schedule>();
	
    @Transient
	@Autowired
	private AccountManager accountManager;
    
	@Transient
	@Autowired
	private ScheduleManager scheduleManager;
	
	@Transient
	@Autowired
	private AccountTransactionManager accountTransactionManager;

	public void setId(long id) {
		this.id = id;
	}

	public long getId() {
		return id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Double getBalance() {
		return balance;
	}

	public void setBalance(Double balance) {
		this.balance = balance;
	}
	
	public List<Schedule> getSchedules() {
		return schedules;
	}

	public void setSchedules(List<Schedule> schedules) {
		this.schedules = schedules;
	}

	public ScheduleManager getScheduleManager() {
		return scheduleManager;
	}

	public void setScheduleManager(ScheduleManager scheduleManager) {
		this.scheduleManager = scheduleManager;
	}

	public String toString() {
		return getName() + " ($" + balance + ")";
	}

	public void addAmount(Double amount) {
		this.balance = balance + amount;
	}

	public Schedule addScheduledTransactions(String string, FrequencyType frequency, int occurrences, Double amount) {
		Schedule schedule = new Schedule(this, name, frequency, occurrences, amount);
		schedules.add(schedule);
		schedule.save();
		schedule.updateRecurrences();
		return schedule;
	}

	public List<AccountTransaction> getUnpaidTransactions() {
		return accountTransactionManager.getUnpaidTransactions(this);
	}

	@Override
	public AccountManager getManager() {
		return accountManager;
	}
	
	public AccountTransaction getFirstUnpaidTransaction() {
		List<AccountTransaction> unpaidTransactions = getUnpaidTransactions();		
		if (unpaidTransactions.size() > 0)
			return unpaidTransactions.get(0);
		else
			return null;
	}
	
	public AccountTransaction getLastUnpaidTransaction() {
		List<AccountTransaction> unpaidTransactions = getUnpaidTransactions();
		int lastIndex = unpaidTransactions.size() - 1;
		if (lastIndex >= 0)
			return unpaidTransactions.get(lastIndex);
		else
			return null;
	}

}